1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use arcdps::imgui::{Selectable, StyleColor, Ui};
use std::borrow::Cow;
use strum::{IntoEnumIterator, VariantArray};

/// Renders a combo box for items from an iterator.
// TODO: make more generic?
pub fn combo<T>(
    ui: &Ui,
    label: impl AsRef<str>,
    all: impl IntoIterator<Item = T>,
    current: &mut T,
    item_label: impl Fn(&T) -> Cow<str>,
    item_color: impl Fn(&T) -> Option<[f32; 4]>,
) -> bool
where
    T: PartialEq,
{
    let mut changed = false;
    if let Some(_token) = ui.begin_combo(label, item_label(current).as_ref()) {
        for entry in all {
            let _style =
                item_color(&entry).map(|color| ui.push_style_color(StyleColor::Text, color));
            let selected = entry == *current;
            if Selectable::new(item_label(&entry).as_ref())
                .selected(selected)
                .build(ui)
            {
                changed = true;
                *current = entry;
            }
            if selected {
                ui.set_item_default_focus();
            }
        }
    }
    changed
}

/// Renders a combo box for an enum implementing [`IntoEnumIterator`].
pub fn enum_combo<T>(ui: &Ui, label: impl AsRef<str>, current: &mut T) -> bool
where
    T: PartialEq + AsRef<str> + IntoEnumIterator,
{
    let mut changed = false;
    if let Some(_token) = ui.begin_combo(label, &current) {
        for entry in T::iter() {
            let selected = entry == *current;
            if Selectable::new(&entry).selected(selected).build(ui) {
                changed = true;
                *current = entry;
            }
            if selected {
                ui.set_item_default_focus();
            }
        }
    }
    changed
}

/// Renders a combo box for an enum implementing [`VariantArray`].
pub fn enum_combo_array<T>(ui: &Ui, label: impl AsRef<str>, current: &mut T) -> bool
where
    T: Clone + PartialEq + AsRef<str> + VariantArray,
{
    let mut changed = false;
    if let Some(_token) = ui.begin_combo(label, &current) {
        for entry in T::VARIANTS {
            let selected = *entry == *current;
            if Selectable::new(&entry).selected(selected).build(ui) {
                changed = true;
                *current = entry.clone();
            }
            if selected {
                ui.set_item_default_focus();
            }
        }
    }
    changed
}